<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。
//  JCAT 由中国团队开发维护，是一个国际性的项目。
//  正在使用的这个版本是：0.3.1 / SVN信息：$Id: class.JCAT_UICtrlHtmlMultiItem.php 1122 2008-10-28 02:42:58Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [HTTP下载] http://jcat.JeCat.cn/download
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.cn/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.cn/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/





/**
 * What's this Class ?
 *
 * @author		alee
 * @access		public
 */
abstract class JCAT_UICtrlHtmlMultiItem extends JCAT_UICtrlFormHtmlBase
{
	/**
	 * 
	 *
	 * @access	public
	 * @return	void
	 */
	public function GetDataLength()
	{
		$aIterator = $this->CreateItemIterator() ;
		$aIterator->First() ;
		$nCount = 0 ;
		
		while( !$aIterator->IsDone() )
		{
			$aItem = $aIterator->Current() ;
			if($aItem->GetActive())
				$nCount ++ ;
			
			$aIterator->Next() ;
		}
		
		return $nCount ;
	}


	/**
	 * 取得控件值
	 * 
	 * @access	public
	 * @return	string, int
	 */
	public function GetExchangeData()
	{
		// 分隔符
		$sDelimiter = $this->GetMultiItemDataDelimiter() ;
		$RetData = ($sDelimiter===self::BIT_DELIMITER)? 0: array() ;
		
		$aIterator = $this->CreateItemIterator() ;
		$aIterator->First() ;
		
		$nSelected = 0 ;
		while( !$aIterator->IsDone() )
		{
			$aItem = $aIterator->Current() ;
			if($aItem->GetActive())
			{
				$nSelected ++ ;
				// 分隔：位操作
				if($sDelimiter===self::BIT_DELIMITER)
				{
					$RetData|= $aItem->GetValue() ;
				}
				
				// 分隔：字符分隔符
				else 
				{
					$RetData[] = $aItem->GetValue() ;
				}
			}

			$aIterator->Next() ;
		}
		
		if($nSelected===0)
		{
			return $this->NullSelectedValue ;
		}
		
		else 
		{
			// 用分隔符合并数组
			if(is_array($RetData))
			{
				$RetData = implode($sDelimiter,$RetData) ;
			}
	
			return $RetData ;
		}
	}
	
	/**
	 * 在此简单的从一个 HTML Form 中取得用户输入
	 * 更高级的 方式，请在派生类中 重載此函数
	 * 
	 * @access	public
	 * @return	void
	 */
	public function SetDataFromSubmited()
	{
		$sInputName = $this->GetName() ;
		if( isset($_REQUEST[$sInputName]) )
		{
			$this->SetDataByExchange($_REQUEST[$sInputName]) ;
		}
		
		else
		{
			$this->SetItemActiveAll(false) ;
		}
	}
	
	/**
	 * 设置无选项被选中时控件的值
	 *
	 * @access	public
	 * @param	$Value
	 * @return	old_value
	 */
	public function SetNullValue($Value)
	{
		// 参数检验
		JCAT_ASSERT::ASSERT_ISTHESE($Value,array('array','string','number')) ;
		
		$old_value = $this->NullSelectedValue ;
		$this->NullSelectedValue = $Value ;
		return $old_value ;
	}


	/**
	 * 设置控件值
	 * 
	 * @access	public
	 * @param	$Value	'array','string','number'	What's this Parameter ?
	 * @return	old_var
	 */
	public function SetDataByExchange( $Value )
	{
		// 参数检验
		JCAT_ASSERT::ASSERT_ISTHESE($Value,array('array','string','number')) ;

		// 字符串/整数 格式
		if( JCAT_Global::IsThese($Value,array('string','number')) )
		{
			// 分隔符
			$sDelimiter = $this->GetMultiItemDataDelimiter() ;
		
			// 分隔：位操作
			if($sDelimiter===self::BIT_DELIMITER)
			{
				$this->_SetDataByBitOperate(&$Value) ;
			}
			
			// 分隔：字符分隔符
			else 
			{
				$arrValues = explode($sDelimiter,$Value) ;
				$this->_SetArrayData($arrValues);
			}
		}

		// 数组格式
		else if( is_array($Value) )
		{
			$this->_SetArrayData($Value);
		}

		// 非法
		else
		{
			JCAT_ASSERT::ASSERT_(0,'!?') ;
		}

	}
	

	/**
	 * what's this
	 * 
	 * @access	private
	 * @param	$arrData	array		what's this
	 * @return	void
	 */
	private function _SetArrayData(array &$arrData)
	{
		$aIterator = $this->CreateItemIterator() ;
		$aIterator->First() ;
		while( !$aIterator->IsDone() )
		{
			$aItem = $aIterator->Current() ;

			$aItem->SetActive(in_array($aItem->GetValue(),$arrData)) ;

			$aIterator->Next() ;
		}		
	}
	
	/**
	 * what's this
	 * 
	 * @access	private
	 * @param	$nData	number		what's this
	 * @return	void
	 */
	private function _SetDataByBitOperate($nData)
	{
		JCAT_ASSERT::ASSERT_( is_numeric($nData)
			, JCAT_Language::SentenceEx('遇到非法的选项值：“%s”；以“按位操作”保存多项选择控件的值时，各选项值必须为数字格式。','JCAT',null,$nData));
	
		if( is_string($nData) )
		{
			$nData = intval($nData) ;
		}
				
		$aIterator = $this->CreateItemIterator() ;
		$aIterator->First() ;
		while( !$aIterator->IsDone() )
		{
			$aItem = $aIterator->Current() ;

			$aItem->SetActive( ($aItem->GetValue()&$nData) ) ;

			$aIterator->Next() ;
		}			
	}
	
	
	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @param	$aItem	JCAT_UICtrlItem	What's this Parameter ?
	 * @return	int
	 */
	public function AddItem( JCAT_UICtrlItem $aItem ) 
	{
		if( !in_array($aItem,$this->arrItems) )
		{
			$this->arrItems[] = $aItem ;
			$arrKeys = array_keys($this->arrItems) ;
			$nNewIdx = array_pop($arrKeys) ;
			
			// 重新设定 Active 转台
			$this->SetItemActive( $nNewIdx, $aItem->GetActive() ) ;
			
			return $nNewIdx ;
		}
		
		return -1 ;
	}

	/**
	 * AddItem() 的别名
	 *
	 * @access	public
	 * @return	void
	 */
	public function AddOption()
	{
		$arrArgs = func_get_args() ;
		return call_user_func_array(array($this,'AddItem'),$arrArgs) ;
	}
	
	/**
	 * 移除 Item
	 *
	 * @access	public
	 * @return	int
	 */
	public function RemoveItem( JCAT_UICtrlItem $aItem )
	{
		foreach ($this->arrItems as $nIdx=>$aItemInStack)
		{
			if($aItemInStack===$aItem)
			{
				unset($this->arrItems[$nIdx]) ;
				return $nIdx ;
			}
		}
		
		return -1 ;
	}
	
	
	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @return	int
	 */
	public function GetItemCount(  ) 
	{
		return count($this->arrItems) ;
	}



	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @param	$nIdx	int	What's this Parameter ?
	 * @return	JCAT_UICtrlItem,null
	 */
	public function GetItem( $nIdx ) 
	{
		JCAT_ASSERT::ASSERT_INT($nIdx) ;
		return $this->arrItems[$nIdx]? $this->arrItems[$nIdx]: null ;
	}



	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @return	JCAT_ArrayIterator
	 */
	public function CreateItemIterator() 
	{
				return new JCAT_ArrayIterator($this->arrItems) ;
	}



	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @param	$nIdx	int	What's this Parameter ?
	 * @param	$bActive=true		What's this Parameter ?
	 * @return	old_var
	 */
	public function SetItemActive( $nIdx,  $bActive=true ) 
	{
		JCAT_ASSERT::ASSERT_INT($nIdx) ;
		
		// 先 取消 原有 选中 的Item
		if( !$this->GetMultiple() and $bActive and ($nActiveIdx=$this->GetFirstActiveItem())!=$nIdx)
			$this->SetItemActive($nActiveIdx,false) ;

		$aItem = $this->GetItem($nIdx) ;
		JCAT_ASSERT::ASSERT_INSTANCE($aItem,'JCAT_UICtrlItem') ;
		
		return $aItem->SetActive($bActive) ;
	}



	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @param	$nIdx	int	What's this Parameter ?
	 * @return	bool
	 */
	public function GetItemActive( $nIdx ) 
	{
		JCAT_ASSERT::ASSERT_INT($nIdx) ;
		
		$aItem = $this->GetItem($nIdx) ;
		JCAT_ASSERT::ASSERT_INSTANCE($aItem,'JCAT_UICtrlItem') ;
		
		return $aItem->GetActive() ;
	}

	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @param	$nIdx	int	What's this Parameter ?
	 * @return	int
	 */
	public function GetFirstActiveItem() 
	{
		$aIterator = $this->CreateItemIterator() ;
		$aIterator->First() ;
		
		while( !$aIterator->IsDone() )
		{
			$aItem = $aIterator->Current() ;
			if($aItem->GetActive())
				return $aIterator->CurrentKey() ;
			
			$aIterator->Next() ;
		}
		
		return -1 ;
	}


	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @param	$bActive=true		What's this Parameter ?
	 * @return	void
	 */
	public function SetItemActiveAll(  $bActive=true ) 
	{
		$aIterator = $this->CreateItemIterator() ;
		$aIterator->First() ;
		
		while( !$aIterator->IsDone() )
		{
			$aItem = $aIterator->Current() ;
			$aItem->SetActive($bActive) ;
			
			$aIterator->Next() ;
		}
	}



	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @param	$sDelimiter	string	What's this Parameter ?
	 * @return	old_var
	 */
	public function SetMultiItemDataDelimiter( $sDelimiter ) 
	{
		JCAT_ASSERT::ASSERT_STRING($sDelimiter) ;
		
		$old_var = $this->sMultiItemDataDelimiter ;
		$this->sMultiItemDataDelimiter = $sDelimiter ;
		return $old_var ;
	}


	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @return	string
	 */
	public function GetMultiItemDataDelimiter() 
	{ return $this->sMultiItemDataDelimiter ; }


	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @param	$bMultiple	bool	What's this Parameter ?
	 * @return	old_var
	 */
	public function SetMultiple( $bMultiple=true ) 
	{
		if( $sMsg=JCAT_Language::SentenceEx('该类型（%s）的控件无法设置为多项选取。','JCAT',null,get_class($this)) and !$this->bCanbeMultiple and $bMultiple )
			throw new JCAT_Exception( $sMsg, __macro_exception_code__ ) ;
		
		$old_var = $this->bMultiple ;
		$this->bMultiple = $bMultiple? true: false ;
		return $old_var ;
	}



	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @return	bool
	 */
	public function GetMultiple(  ) 
	{
		return $this->bMultiple ;
	}


	protected function SetCanbeMultiple($bCanbeMultiple=true)
	{
		$this->bCanbeMultiple = $bCanbeMultiple? true: false ;
	}

	
	// 属性 ///////////////////////////////////////////////////////////////////////////////

	/**
	 * What's this Attribute ?
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sMultiItemDataDelimiter = ';' ;


	private $arrItems = array() ;
	
	
	protected $bCanbeMultiple = false ;
	
	protected $bMultiple = false ;
	
	private $NullSelectedValue = '' ;

	
	/**
	 * 位操作界定符
	 * 
	 * @access	const
	 * @var		string
	 */
	const BIT_DELIMITER = 'BIT_DELIMITER' ;
}
?>